package grafikon;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.JCheckBox;
import javax.swing.JPanel;

/**
 *
 * @author Csüti
 */
public class gPanel extends JPanel {

    private int steps;                                              //Scale variable               
    ArrayList<CoordsList> coords;                                   //CoordsList ArrayList for the lists that should be shown at the graph
    private boolean crossEnabled = true;                            //boolean for the cross enable
    private boolean showTextEnabled = true;                         //boolean for the text enable
    private boolean netEnabled = true;                              //boolean for the net enable

    public gPanel(int steps, ArrayList<CoordsList> coords) {
        super();

        setBackground(Color.WHITE);
        this.steps = steps;
        this.coords = coords;
        this.setPreferredSize(new java.awt.Dimension(750, 750));
        setMinimumSize(new java.awt.Dimension(750, 750));
    }

    public void setSteps(int s) {
        steps = s;
    }

    public void setCrossEnabled(boolean b) {
        crossEnabled = b;
        repaint();
    }

    public void setNetEnabled(boolean b) {
        netEnabled = b;
        repaint();
    }

    public int getSteps() {
        return steps;
    }

    public boolean getCrossEnabled() {
        return crossEnabled;
    }

    public boolean getNetEnabled() {
        return netEnabled;
    }

    private void drawStep(Graphics g, int mid_x, int mid_y, int lkh, int lk) {

        for (int i = 0; i < steps; i++) {
            g.drawLine(mid_x - lkh, (mid_y * i) / steps, mid_x + lkh, (mid_y * i) / steps);
        }
        for (int i = 0; i < steps; i++) {
            g.drawLine(mid_x - lkh, mid_y + (mid_y * i) / steps, mid_x + lkh, mid_y + (mid_y * i) / steps);
        }
        for (int i = 0; i < steps; i++) {
            g.drawLine((mid_x * i) / steps, mid_y - lkh, (mid_x * i) / steps, mid_y + lkh);
        }
        for (int i = 0; i < steps; i++) {
            g.drawLine(mid_x + (mid_x * i) / steps, mid_y - lkh, mid_x + (mid_x * i) / steps, mid_y + lkh);
        }
    }

    @Override
    public void paintComponent(Graphics g) {

        // Paint background
        super.paintComponent(g);
        // Get the drawing area 
        int dy = getSize().height;
        int dx = getSize().width;
        int mid_y = dy / 2;
        int mid_x = dx / 2;

        // Set current drawing color
        g.setColor(Color.BLACK);

        if (netEnabled) {
            drawNet(g, dx, dy);
        }
        // Draw a rectangle centered at the mid-point
        g.drawLine(0, mid_y, dx, mid_y);
        g.drawLine(mid_x, 0, mid_x, dy);
        //lépésközvonalak
        drawStep(g, mid_x, mid_y, 5, steps); //draw steps
        double max_x = 0;
        double max_y = 0;
        double highestX = 0, highestY = 0;

        for (int i = 0; i < coords.size(); i++) //calculate highest x and y coord
        {
            ArrayList<Coords> tmp = (ArrayList<Coords>) coords.get(i).coords.clone();
            if (tmp.size() > 0) {
                Collections.sort(tmp);
                if (Math.abs(tmp.get(tmp.size() - 1).x * 100 + 15) > max_x
                        || Math.abs(tmp.get(0).x * 100 + 15) > max_x) {
                    max_x = (Math.abs(tmp.get(tmp.size() - 1).x * 100 + 15) > Math.abs(tmp.get(0).x * 100 + 15))
                            ? Math.abs(tmp.get(tmp.size() - 1).x * 100 + 15) : Math.abs(tmp.get(0).x * 100 + 15);
                    highestX = Math.abs(tmp.get(tmp.size() - 1).x);
                }

                tmp = (ArrayList<Coords>) coords.get(i).coords.clone();
                Collections.sort(tmp, new CoordComparator());
                if (Math.abs(tmp.get(tmp.size() - 1).y * 100 + 15) > max_y
                        || Math.abs(tmp.get(0).y * 100 + 15) > max_y) {
                    max_y = (Math.abs(tmp.get(tmp.size() - 1).y * 100 + 15) > Math.abs(tmp.get(0).y * 100 + 15))
                            ? Math.abs(tmp.get(tmp.size() - 1).y * 100 + 15) : Math.abs(tmp.get(0).y * 100 + 15);
                    highestY = Math.abs(tmp.get(tmp.size() - 1).y);
                }
            }
        }

        drawText(g, mid_x, mid_y, max_x, max_y, highestX, highestY);

        for (int i = 0; i < coords.size(); i++) //calculate highest x and y coord
        {
            if (coords.get(i).coords.size() > 0) {
                g.setColor(coords.get(i).color);
                drawGraph(g, mid_x, mid_y, coords.get(i).coords, max_x, max_y);
            }
        }

    } // paintComponent

    private void drawGraph(Graphics g, int mid_x, int mid_y, ArrayList<Coords> c, double max_x, double max_y) {
        //draw small x's at the coordinates
        if (crossEnabled) {
            for (int i = 1; i < c.size() + 1; i++) {
                g.drawLine(mid_x + (int) ((c.get(i - 1).x * mid_x * 100) / max_x) - 2, mid_y - (int) ((c.get(i - 1).y * mid_y) / max_y * 100) - 2,
                        mid_x + (int) ((c.get(i - 1).x * mid_x * 100) / max_x) + 2, mid_y - (int) ((c.get(i - 1).y * mid_y) / max_y * 100) + 2);

                g.drawLine(mid_x + (int) ((c.get(i - 1).x * mid_x * 100) / max_x) - 2, mid_y - (int) ((c.get(i - 1).y * mid_y) / max_y * 100) + 2,
                        mid_x + (int) ((c.get(i - 1).x * mid_x * 100) / max_x) + 2, mid_y - (int) ((c.get(i - 1).y * mid_y) / max_y * 100) - 2);
            }
        }

        //draw the actual graphics
        for (int i = 1; i < c.size(); i++) {


            g.drawLine(mid_x + (int) ((c.get(i - 1).x * mid_x * 100) / max_x), mid_y - (int) ((c.get(i - 1).y * mid_y) / max_y * 100),
                    mid_x + (int) ((c.get(i).x * mid_x * 100) / max_x), mid_y - (int) ((c.get(i).y * mid_y * 100) / max_y));
        }
    }

    public void setShowTextEnabled(boolean selected) {
        showTextEnabled = selected;
        repaint();
    }

    public boolean getShowTextEnabled() {
        return showTextEnabled;
    }

    private void drawText(Graphics g, int mid_x, int mid_y, double max_x, double max_y, double hx, double hy) {
        if (showTextEnabled) {
            g.drawString("X", 2 * mid_x - 15, mid_y + 20);   //X axis on the graph       
            g.drawString("Y", mid_x + 20, 15);             //Y axis on the graph

            double[][] scaleValues = getScaleValues(hx, hy);
            //  System.out.println(max_x+"  ||||||||   "+ max_y);
            int[] hosszX = getRequiredSpace(scaleValues);

            if (max_x == new Double(0)) {
                max_x = steps;
            }
            if (max_y == new Double(0)) {
                max_y = steps;
            }

            for (int i = 0; i < steps; i++) {
                g.drawString("" + scaleValues[i][1], mid_x - 35, (mid_y * i) / steps);
            }
            for (int i = 0; i < steps; i++) {
                g.drawString("" + scaleValues[i][1] * (-1), mid_x + 10, 2 * mid_y - mid_y * i / steps);
            }
            for (int i = 0; i < steps; i++) {
                g.drawString("" + scaleValues[i][0] * (-1), mid_x * i / steps, mid_y + 20);
            }
            for (int i = 0; i < steps; i++) {
                g.drawString("" + scaleValues[i][0], 2 * mid_x - mid_x * i / steps, mid_y - 20);
            }
        }
    }

    public int[] getRequiredSpace(double[][] scales) {
        int[] tmp = new int[steps];
        for (int i = 1; i < steps; i++) {
            String temp = "" + scales[i][1];
            tmp[tmp.length - i] = temp.length();
        }
        return tmp;
    }

    public double[][] getScaleValues(double mx, double my) {
        double[][] tmp = new double[steps][2];
        for (int i = 0; i < steps; i++) {
            if (mx == 0) {
                tmp[steps - 1 - i][0] = i + 1;
            } else {

                tmp[steps - 1 - i][0] =/* mx * i/steps;*/ Double.parseDouble(("" + (mx * (i + 1) / steps)).substring(0, 3));

            }
        }

        for (int i = 0; i < steps; i++) {
            if (my == 0) {
                tmp[steps - 1 - i][1] = i + 1;
            } else {

                tmp[steps - 1 - i][1] = /*my * i/steps;*/ Double.parseDouble(("" + (my * (i + 1) / steps)).substring(0, 3));

            }
        }
        return tmp;
    }

    private void drawNet(Graphics g, int dx, int dy) {
        g.setColor(Color.LIGHT_GRAY);
        for (int i = 0; i < steps * 2; i++) {
            g.drawLine(dx * i / (steps * 2), 0, dx * i / (steps * 2), dy);

        }
        for (int i = 0; i < steps * 2; i++) {
            g.drawLine(0, dy * i / (steps * 2), dx, dy * i / (steps * 2));
        }
        g.setColor(Color.black);
    }
}
